import * as THREE from "three"
import renderOrderEnum from "../enum/renderOrder.enum"
import { InstancedPinStemMaterial } from "../material/PinMaterial"
import { pinItemData } from "../module/PinsModule"
import Logger from "../utils/Logger"
const fe = new InstancedPinStemMaterial()
const ve = new Logger("InstancedPinHeads")
export default class InstancedPinLines extends THREE.InstancedMesh<THREE.BufferGeometry, InstancedPinStemMaterial> {
  maxCount: number
  stemVectorArray: Float32Array
  stemVectorAttrib: THREE.InstancedBufferAttribute
  pinHeadMatrixArray: any[]
  pinHeadMatrixAttrib: any[]
  opacityArray: Float32Array
  opacityAttrib: THREE.InstancedBufferAttribute
  posMatrix: THREE.Matrix4
  isLine: boolean
  declare isMesh: any
  constructor(e: number) {
    const t = new THREE.BufferGeometry()
    const i = new Float32Array(6)
    i[0] = i[1] = i[2] = 0
    i[3] = 1
    i[4] = 1
    i[5] = 1
    t.setAttribute("position", new THREE.BufferAttribute(i, 3))
    const s = new Float32Array(3 * e)
    const r = new THREE.InstancedBufferAttribute(s, 3)
    t.setAttribute("stemVector", r)
    const o = new Float32Array(e)
    const a = new THREE.InstancedBufferAttribute(o, 1)
    t.setAttribute("instanceAlpha", a)
    const l = []
    const c = []
    for (let i = 0; i < 4; i++) {
      const s = new Float32Array(4 * e)
      const r = new THREE.InstancedBufferAttribute(s, 4)
      t.setAttribute(`pinHeadMatrixCol${i}`, r)
      l.push(s)
      c.push(r)
    }
    super(t, fe, e)
    this.maxCount = e
    this.stemVectorArray = s
    this.stemVectorAttrib = r
    this.pinHeadMatrixArray = l
    this.pinHeadMatrixAttrib = c
    this.opacityArray = o
    this.opacityAttrib = a
    this.renderOrder = renderOrderEnum.lines
    this.posMatrix = new THREE.Matrix4()
    this.isLine = true
    this.isMesh = false
  }
  update(e: pinItemData[], t) {
    let i = 0

    for (const t of e) {
      if (!t.visible || !t.stemEnabled || t.stemLength < 0.001) continue
      if (i >= this.maxCount) {
        ve.error("Instance count is too small!")
        continue
      }

      this.posMatrix.setPosition(t.anchorPosition)
      this.setMatrixAt(i, this.posMatrix)
      this.opacityArray[i] = t.opacity * t.opacityAnimation.value
      const e = 3 * i
      t.pinHeadObjPosition.toArray(this.stemVectorArray, e)
      let n = 0
      for (let e = 0; e < 4; e++) for (let s = 0; s < 4; s++) this.pinHeadMatrixArray[e][s + 4 * i] = t.pinHeadMatrix.elements[n++]
      i++
    }
    this.count = i
    this.visible = this.count > 0
    this.instanceMatrix.needsUpdate = !0
    this.stemVectorAttrib.needsUpdate = !0
    for (const e of this.pinHeadMatrixAttrib) e.needsUpdate = !0
    this.opacityAttrib.needsUpdate = !0
    fe.uniforms.resolution.value.set(t.width, t.height)
    fe.uniformsNeedUpdate = !0
  }
}
